home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 6 / The Arsenal Files 6 (Arsenal Computer).ISO / os2 / am4pmsrc.zip / AM4PM.C next >
C/C++ Source or Header  |  1994-05-22  |  36KB  |  1,337 lines

  1. // Thomas Answering machine for PM
  2.  
  3. // File:          AM4PM.c
  4. // Description:   The PM code
  5.  
  6. // History
  7. // 930214 TO      Now it exists...
  8. // 930430 TO      Change sub command interface to subroutines
  9. // 930510 TO      Sets timeout to zero to force reading thread to exit
  10. // 930517 TO      External queue for releasing COM port
  11. // 930525 TO      Can read and create ZyXEL files
  12. // 930528 TO      Speed impovments
  13. // 930529 TO      More speed impovments
  14. // 930530 TO      AMStartListenDLECode can set receive mode
  15. // 930531 TO      RING.CMD renamed to RING.AMC
  16. // 930531 TO      Can start AMC scripts from AM4PMCmd. Calls PLAY.AMC and DELETE.AMC
  17. // 930601 TO      Uses EAs for message length
  18. // 930603 TO      Empties input queue before playing or recording file
  19. // 930604 TO      EA for CID text
  20. // 930605 TO      Calls CID.AMC if a string starting with 'TIME' is received.
  21. // 930607 TO      Can release COM-port from script
  22. // 930613 TO      New functions: AMWriteIni, AMReadIni
  23. // 930614 TO      Uses the variable pool for the variable vAMRings
  24. // 930615 TO      New variable: vAMMsgs
  25. // 930619 TO      Uses container class
  26. // 930620 TO      Saves window pos and restores COM settings for hot handle
  27. // 930620 TO      Restores setting when closing COM port
  28. // 930628 TO      New user interface: container
  29. // 930710 TO      Default position if no info saved
  30. // 930711 TO      Recording of messages
  31. // 930718 TO      AMSendW returns "!" when error
  32. // 931002 TO      New functions: AMInpm AMOutp
  33. // 931003 TO      New function: AMTrimFileEnd
  34. // 931006 TO      AMPlayFile can return user events
  35. // 931011 TO      Calls EXIT.AMC at exit
  36. // 931013 TO      New ZyXEL file formats that store DLE codes
  37. // 940125 TO      New parameter to AMPlayFile, AMWaitDLECode indicating what DLE code to listen for
  38. // 940226 TO      Better Hayes command processing
  39. // 940227 TO      Added AMLog and Rexx exits for SAY and TRC output
  40. // 940312 TO      Cleaning up queue in SendHayes2
  41. // 940522 TO      Calling SendHayes2 in EndRec
  42.  
  43. #define INCL_WIN
  44. #define INCL_BASE
  45.  
  46. #include <os2.h>
  47.  
  48. #include <stddef.h>
  49. #include <string.h>
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52.  
  53. #include "am4pm.h"
  54. #include "am4pmdlg.h"
  55.  
  56.  
  57. #define CNRCOLS 4 // Number of fields in container
  58.  
  59. // Core structure for container
  60. typedef struct
  61. {
  62.    MINIRECORDCORE mc;
  63.    HPOINTER hptr;
  64.    CDATE date;
  65.    CTIME time;
  66.    ULONG ulLen;
  67.    PSZ pszDescr;
  68.    PSZ pszFile;
  69. } MYCORE;
  70.  
  71. typedef MYCORE * PMYCORE;
  72.  
  73.  
  74. MRESULT EXPENTRY ClientWndProc(HWND, USHORT, MPARAM, MPARAM);
  75. MRESULT EXPENTRY Am4PmWndProc(HWND, ULONG, MPARAM, MPARAM);
  76.  
  77.  
  78. CHAR szVersion[]="v0.13d (22 May 1994)";
  79. CHAR szIniFile[]="AM4PM.INI";
  80. CHAR szIniAm4Pm[]="AM4PM";
  81. CHAR szMsgFile[]="AM4PM.MSG";
  82. CHAR szAppName[]="Am4Pm";
  83.  
  84. static CHAR szAppPosKey[]="WinPosOrg";
  85. static CHAR szAppPosOrgKey[]="WinPos";
  86. // static CHAR szAM4PMClass[]="AM4PM";
  87.  
  88. PCHAR pszDCEVer=NULL;
  89.  
  90. HAB hab;
  91. HWND hwndFrame, hwndClient, hwndMenu;
  92. PFNWP pfnwpFrame;
  93.  
  94. volatile PARAMETERBLOCK ParamBlock;
  95. volatile BOOL fDebug=FALSE, fWarnings=FALSE, fAbortCmd=FALSE;
  96. static BOOL fNewStyle=TRUE;
  97. HINI hiniAM;
  98. volatile ULONG ulRecMessages=0;
  99.  
  100. static HPOINTER hptrMsg;
  101.  
  102. const CHAR szEALen[]="AM4PM.LEN";
  103. const CHAR szEADescr[]=".SUBJECT";
  104. const CHAR szEAType[]=".TYPE";
  105. CHAR szOurEAType[]="ZyXEL Voice";
  106.  
  107. static SWCNTRL swctl;
  108. static HSWITCH hswitch;
  109. static PID pid;
  110. static CHAR szTitle[]="Am4Pm";
  111. static CHAR szExtQueue[]="\\QUEUES\\AM4PM";
  112.  
  113. static PCHAR Rates[]=
  114. {
  115.    "9600",
  116.    "19200",
  117.    "38400",
  118.    "57600",
  119.    "76800"
  120. };
  121.  
  122.  
  123. static PCHAR ComDev[]=
  124. {
  125.    "COM1",
  126.    "COM2",
  127.    "COM3",
  128.    "COM4"
  129. };
  130.  
  131.  
  132. BOOL IniPutL
  133. (
  134.    CHAR * szKey,
  135.    LONG lValue
  136. )
  137. {
  138.    CHAR szStr[10];
  139.  
  140.    return PrfWriteProfileString(hiniAM, szIniAm4Pm, szKey, _ltoa(lValue, szStr, 10));
  141. }
  142.  
  143.  
  144. LONG IniGetL
  145. (
  146.    CHAR * szKey,
  147.    LONG lDefault
  148. )
  149. {
  150.    CHAR szStr[10], szDef[10];
  151.  
  152.    PrfQueryProfileString(hiniAM, szIniAm4Pm, szKey, _ltoa(lDefault, szDef, 10), szStr, sizeof szStr);
  153.    return atol(szStr);
  154. }
  155.  
  156.  
  157. BOOL IniPutSZ
  158. (
  159.    CHAR * szKey,
  160.    CHAR * szStr
  161. )
  162. {
  163.    return PrfWriteProfileString(hiniAM, szIniAm4Pm, szKey, szStr);
  164. }
  165.  
  166.  
  167. PCHAR IniGetSZ
  168. (
  169.    CHAR * szKey,
  170.    CHAR * szDefault
  171. )
  172. {
  173.    CHAR szStr[128], * pszNewStr;
  174.  
  175.    PrfQueryProfileString(hiniAM, szIniAm4Pm, szKey, szDefault, szStr, sizeof szStr);
  176.    pszNewStr=strdup(szStr);
  177.    return pszNewStr;
  178. }
  179.  
  180.  
  181. BOOL IniPutBool
  182. (
  183.    CHAR * szKey,
  184.    BOOL bValue
  185. )
  186. {
  187.    return PrfWriteProfileString(hiniAM, szIniAm4Pm, szKey, bValue ? "Y" : "N");
  188. }
  189.  
  190.  
  191. BOOL IniGetBool
  192. (
  193.    CHAR * szKey
  194. )
  195. {
  196.    CHAR szStr[10];
  197.  
  198.    PrfQueryProfileString(hiniAM, szIniAm4Pm, szKey, "N", szStr, sizeof szStr);
  199.    return *szStr=='Y';
  200. }
  201.  
  202. static void IniGetSZP
  203. (
  204.    CHAR * szKey,
  205.    CHAR * szDefault,
  206.    CHAR * volatile * ppch
  207. )
  208. {
  209.    if (*ppch)
  210.       free(*ppch);
  211.  
  212.    *ppch = IniGetSZ(szKey, szDefault);
  213. }
  214.  
  215. void GetIniFile(void)
  216. {
  217.    ParamBlock.fsFlags = 0l;
  218.    ParamBlock.ulBaud=IniGetL("Baud", 38400l); // Baud rate
  219.    ParamBlock.ulRings=IniGetL("Rings", 1l); // Rings before answer
  220.    ParamBlock.ulLastFileID=IniGetL("LastFileID", 0l); // Last ID used for creating file
  221.    DosEnterCritSec();
  222.    IniGetSZP("Com", "COM1", &ParamBlock.szCom); // Com port
  223.    IniGetSZP("ATHangUp", "AT+VLS=0{OK}", &ParamBlock.szATHangUp);
  224.    IniGetSZP("ATVoiceMode", "AT+VSM=%u{OK}", &ParamBlock.szATVoiceMode);
  225.    IniGetSZP("ATVoiceTX", "AT+VTX{CONNECT}", &ParamBlock.szATVoiceTX);
  226.    IniGetSZP("ATVoiceRX", "AT+VRX{CONNECT}", &ParamBlock.szATVoiceRX);
  227.    IniGetSZP("ATVoiceEndTX", "\x10\x03{VCON}", &ParamBlock.szATVoiceEndTX);
  228.    IniGetSZP("ATVoiceCancelTX", "\x10\x14{VCON}", &ParamBlock.szATVoiceCancelTX);
  229.    IniGetSZP("FileMode", "Z", &ParamBlock.szFileMode);
  230.    IniGetSZP("MessagePattern", "M*.ZVD", &ParamBlock.szMessagePattern);
  231.    IniGetSZP("FileExtension", "ZVD", &ParamBlock.szFileExtension);
  232.    DosExitCritSec();
  233.           
  234.    ParamBlock.fTitles=IniGetBool("Titles");
  235.  
  236. // fDebug=IniGetBool("Debug");
  237.    fWarnings=IniGetBool("Warnings");
  238. }
  239.  
  240.  
  241. static void WriteSettings2IniFile(void)
  242. {
  243.    if (fDebug)
  244.       dprintf("Writing settings to ini file\n");
  245.    IniPutSZ("Com", ParamBlock.szCom); // Com port
  246.    IniPutL("Baud", ParamBlock.ulBaud); // Baud rate
  247.    IniPutL("Rings", ParamBlock.ulRings); // Rings before answer
  248.    IniPutBool("Titles", ParamBlock.fTitles);
  249.  
  250.    IniPutBool("Debug", fDebug);
  251.    IniPutBool("Warnings", fWarnings);
  252. }
  253.  
  254.  
  255. void WriteState2IniFile(void)
  256. {
  257.    if (fDebug)
  258.       dprintf("Writing state to ini file\n");
  259.    IniPutL("LastFileID", ParamBlock.ulLastFileID);
  260. }
  261.  
  262.  
  263. #if 0
  264. static ULONG APIENTRY ExcpHandler
  265. (
  266.    PEXCEPTIONREPORTRECORD pExcpRep,
  267.    PEXCEPTIONREGISTRATIONRECORD pExcpReg,
  268.    PCONTEXTRECORD pContext,
  269.    PVOID pData
  270. )
  271. {
  272.    ULONG ulCount;
  273.  
  274.    dprintf("ExceptioNum=%u\n", pExcpRep->ExceptionNum);
  275. // DosAcknowledgeSignalException(XCPT_SIGNAL_INTR);
  276.  
  277.    DosResetEventSem(semStopedReading, &ulCount);
  278.    DosPostEventSem(semStopRead);
  279.    if (fDebug)
  280.       dprintf("Waiting for the other thread to die...\n");
  281.    DosWaitEventSem(semStopedReading, 30000l);
  282.    usGlobalState=GS_ENDING;
  283.    DosPostEventSem(semGoOnRead);
  284.    return 0;
  285. }
  286.  
  287.  
  288. static void CtrlCSig(void)
  289. {
  290.    EXCEPTIONREGISTRATIONRECORD ExcpReg;
  291.  
  292.    ExcpReg.prev_structure=NULL;
  293.    ExcpReg.ExceptionHandler=ExcpHandler;
  294.  
  295.    DosSetExceptionHandler(&ExcpReg);
  296. }
  297. #endif
  298.  
  299.  
  300. ULONG GetSysMSecs(void)
  301. {
  302.    ULONG ulTime;
  303.  
  304.    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &ulTime, sizeof ulTime);
  305.    return ulTime;
  306. };
  307.  
  308.  
  309. void ExtEventThread(PVOID lpVar)
  310. {
  311.    USHORT res;
  312.    ULONG scBuff;
  313.    HQUEUE hQue;
  314.    REQUESTDATA QueueResult;
  315.    BYTE bPrty;
  316.    PVOID pData;
  317.  
  318.    dprintf("Thread for external events started\n");
  319.  
  320.    res=DosCreateQueue(&hQue, QUE_FIFO, szExtQueue);
  321.    if (res)
  322.    {
  323.       LogNumMessage(10, res, NULL); // Error creating queue
  324.       return;
  325.    }
  326.  
  327.    for (;;)
  328.    {
  329. //    DosReadQueue(HQUEUE hq, PREQUESTDATA pRequest, PULONG pcbData, PPVOID ppbuf, ULONG element, BOOL32 wait, PBYTE ppriority, HEV hsem);
  330.       res=DosReadQueue(hQue, &QueueResult, &scBuff, &pData, 0, DCWW_WAIT, &bPrty, 0l);
  331.       if (res)
  332.       {
  333.          LogNumMessage(11, res, NULL); // Error reading queue
  334.          return;
  335.       }
  336.  
  337.       switch (QueueResult.ulData)
  338.       {
  339.       case EQ_RELCOM:
  340.          QueueData(IM_RELEASE, pData, scBuff);
  341.          break;
  342.  
  343.       case EQ_STARTAMC:
  344.          QueueData(IM_STARTAMC, pData, scBuff);
  345.          break;
  346.  
  347.       case EQ_USER:
  348.          QueueData(IM_EXTUSER, pData, scBuff);
  349.          break;
  350.  
  351.       default:
  352.          LogNumMessage(12, QueueResult.ulData, NULL); // Unkown event code
  353.       }
  354.  
  355.       if (pData != NULL)
  356.          DosFreeMem(pData);
  357.    }
  358. }
  359.  
  360.  
  361. static void SizeTheWindow(HWND hwnd)
  362. {
  363.    SHORT cyTop, cyBottom, cyLeft, cyRight;
  364.  
  365.    cyLeft=0;
  366.    cyRight=WinQuerySysValue(HWND_DESKTOP, SV_CYMENU)*20;
  367.    cyTop=WinQuerySysValue(HWND_DESKTOP, SV_CYMENU)*7;
  368.    cyBottom=0;
  369.  
  370.    WinSetWindowPos(hwnd, NULLHANDLE, cyLeft, cyBottom, cyRight-cyLeft, cyTop-cyBottom, SWP_SIZE | SWP_MOVE | SWP_SHOW);
  371. }
  372.  
  373.  
  374. int main
  375. (
  376.    USHORT usArgc,
  377.    PCHAR pchArgv[]
  378. )
  379. {
  380.    HMQ     hmq;
  381.    QMSG    qmsg;
  382.    USHORT i;
  383.    static ULONG flFrameFlags = FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER |
  384.                                FCF_MINMAX | FCF_ICON |
  385. //                             FCF_MENU |
  386. //                             FCF_NOBYTEALIGN |
  387.                                FCF_ACCELTABLE |
  388.                                FCF_TASKLIST;
  389.  
  390.    static ULONG flClientStyle = CCS_MULTIPLESEL | CCS_MINIRECORDCORE | WS_GROUP | WS_TABSTOP | WS_VISIBLE;
  391.  
  392.    hab = WinInitialize(0);
  393.  
  394. // DosError(FERR_DISABLEHARDERR);
  395.  
  396.    hiniAM=PrfOpenProfile(hab, szIniFile);
  397.    if (hiniAM==0l)
  398.    {
  399.       LogMessage(26, NULL);
  400.       return 1;
  401.    }
  402.  
  403.    memset(&ParamBlock, 0, sizeof ParamBlock);
  404.  
  405.    GetIniFile();
  406.  
  407.    for (i=1; i<usArgc; i++)
  408.    {
  409.       if (pchArgv[i][0]=='-' || pchArgv[i][0]=='/')
  410.       {
  411.          switch (pchArgv[i][1])
  412.          {
  413.          case 'd':
  414.             fDebug=TRUE;
  415.             break;
  416.  
  417.          case 'o':
  418.             fNewStyle=FALSE;
  419.             break;
  420.  
  421.          default:
  422.             if (fDebug)
  423.                dprintf("Unkown switch '%c'\n", pchArgv[i][1]);
  424.          }
  425.       }
  426.    }
  427.  
  428.    hmq = WinCreateMsgQueue(hab, 0);
  429.  
  430.    if (fDebug)
  431.    {
  432.       InitDebug();
  433.       dprintf("\nAnswering machine for PM\nVer %s\n", szVersion);
  434.       dprintf("Debugmode=ON\n");
  435.    }
  436.  
  437.    if (fWarnings)
  438.       dprintf("Warnings=ON\n");
  439.  
  440.    // Load resources
  441.    hptrMsg = WinLoadPointer(HWND_DESKTOP, NULLHANDLE, IDI_MSG);
  442.  
  443.    if (fNewStyle)
  444.    {
  445. //    WinRegisterClass(hab, szAM4PMClass, Am4PmWndProc, CS_SIZEREDRAW, 0l);
  446.  
  447.       hwndFrame=WinCreateStdWindow(HWND_DESKTOP, 0, &flFrameFlags, WC_CONTAINER, szTitle, flClientStyle, 0, IDD_MAIN, &hwndClient);
  448.       WinSetOwner(hwndClient, hwndFrame);
  449.       pfnwpFrame=WinSubclassWindow(hwndFrame, Am4PmWndProc);
  450.       hwndMenu=WinLoadMenu(HWND_OBJECT, 0, IDM_PU);
  451.       WinSendMsg(hwndFrame, WM_CREATED, 0l, 0l);
  452.       if (!WinRestoreWindowPos(szAppName, szAppPosKey, hwndFrame))
  453.          SizeTheWindow(hwndFrame);
  454.    }
  455.    else
  456.    {
  457.       hwndFrame=WinLoadDlg(HWND_DESKTOP, HWND_DESKTOP, (PFNWP)ClientWndProc, 0l, IDD_MAIN, 0l);
  458.  
  459.       // Attach menu to window
  460.       WinLoadMenu(hwndFrame, 0, IDD_MAIN);
  461.       WinSendMsg(hwndFrame, WM_UPDATEFRAME, MPFROM2SHORT(FCF_MENU, 0), 0l);
  462.    
  463.       // Add to switch list
  464.       WinQueryWindowProcess(hwndFrame, &pid, NULL);
  465.       swctl.hwnd = hwndFrame;                /* window handle      */
  466.       swctl.hwndIcon = 0l;
  467.       swctl.hprog = 0l;                      /* program handle     */
  468.       swctl.idProcess = pid;                 /* process identifier */
  469.       swctl.idSession = 0l;                  /* session identifier */
  470.       swctl.uchVisibility = SWL_VISIBLE;     /* visibility         */
  471.       swctl.fbJump = SWL_JUMPABLE;           /* jump indicator     */
  472.       strcpy(swctl.szSwtitle, szTitle);      /* program name       */
  473.       hswitch = WinAddSwitchEntry(&swctl);
  474.    }
  475.  
  476.  
  477.    _beginthread(ExtEventThread, NULL, RSTACKSIZE, NULL);
  478.    _beginthread(WriteModemThread, NULL, RSTACKSIZE, NULL);
  479.  
  480. // WinSetFocus(HWND_DESKTOP, hwndClient);
  481.  
  482.    while (WinGetMsg(hab, &qmsg, 0l, 0, 0))
  483.          WinDispatchMsg(hab, &qmsg);
  484.  
  485.    if (fNewStyle)
  486.       WinStoreWindowPos(szAppName, szAppPosKey, hwndFrame);
  487.  
  488.    WinDestroyWindow(hwndMenu);
  489.    WinDestroyWindow(hwndFrame);
  490.    WinDestroyMsgQueue(hmq);
  491.    WriteState2IniFile();
  492.  
  493.    PrfCloseProfile(hiniAM);
  494.  
  495.    // Release PM resources
  496.    WinDestroyPointer(hptrMsg);
  497.    WinTerminate(hab);
  498.    return 0;
  499. }
  500.  
  501.  
  502. MRESULT EXPENTRY AboutDlgProc
  503. (
  504.    HWND hwnd,
  505.    USHORT msg,
  506.    MPARAM mp1,
  507.    MPARAM mp2
  508. )
  509. {
  510.    switch (msg)
  511.    {
  512.    case WM_INITDLG:
  513.       WinSetDlgItemText(hwnd, IDC_VERSION, szVersion);
  514.       if (pszDCEVer != NULL)
  515.          WinSetDlgItemText(hwnd, IDC_DCEVER, pszDCEVer);
  516.       return FALSE;
  517.  
  518.    case WM_COMMAND:
  519.       switch (COMMANDMSG(&msg)->cmd)
  520.       {
  521.       case DID_OK:
  522.          WinDismissDlg(hwnd, TRUE);
  523.          break;
  524.  
  525.       case DID_CANCEL:
  526.          WinDismissDlg(hwnd, FALSE);
  527.          break;
  528.       }
  529.       break;
  530.    }
  531.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  532. }
  533.  
  534.  
  535.  
  536. MRESULT EXPENTRY SettingsDlgProc
  537. (
  538.    HWND hwnd,
  539.    USHORT msg,
  540.    MPARAM mp1,
  541.    MPARAM mp2
  542. )
  543. {
  544.    CHAR szStr[10];
  545.    USHORT i;
  546.  
  547.    switch (msg)
  548.    {
  549.    case WM_INITDLG:
  550.       WinSendDlgItemMsg(hwnd, IDC_COM, EM_SETTEXTLIMIT, MPFROMSHORT(12), 0l);
  551.       for (i=0; i < sizeof ComDev/sizeof ComDev[0]; i++)
  552.          WinSendDlgItemMsg(hwnd, IDC_COM, LM_INSERTITEM, MPFROMSHORT(LIT_END), MPFROMP(ComDev[i]));
  553.  
  554.       WinSendDlgItemMsg(hwnd, IDC_BAUD, EM_SETTEXTLIMIT, MPFROMSHORT(8), 0l);
  555.       for (i=0; i < sizeof Rates/sizeof Rates[0]; i++)
  556.          WinSendDlgItemMsg(hwnd, IDC_BAUD, LM_INSERTITEM, MPFROMSHORT(LIT_END), MPFROMP(Rates[i]));
  557.  
  558.       WinSetDlgItemText(hwnd, IDC_COM, ParamBlock.szCom);
  559.       WinSetDlgItemText(hwnd, IDC_BAUD, _ltoa(ParamBlock.ulBaud, szStr, 10));
  560.       WinSendDlgItemMsg(hwnd, IDC_RINGS, SPBM_SETLIMITS, MPFROMLONG(99l), MPFROMLONG(1l));
  561.       WinSendDlgItemMsg(hwnd, IDC_RINGS, SPBM_SETCURRENTVALUE, MPFROMLONG(ParamBlock.ulRings), NULL);
  562.       WinSendDlgItemMsg(hwnd, IDC_TITLES, BM_SETCHECK, MPFROM2SHORT(ParamBlock.fTitles, 0), NULL);
  563.       return FALSE;
  564.  
  565.    case WM_COMMAND:
  566.       switch (COMMANDMSG(&msg)->cmd)
  567.       {
  568.       case DID_OK:
  569.          WinQueryDlgItemText(hwnd, IDC_COM, sizeof szStr, szStr);
  570.          free(ParamBlock.szCom);
  571.          ParamBlock.szCom=strdup(szStr);
  572.          WinQueryDlgItemText(hwnd, IDC_BAUD, sizeof szStr, szStr);
  573.          ParamBlock.ulBaud=atol(szStr);
  574.          WinSendDlgItemMsg(hwnd, IDC_RINGS, SPBM_QUERYVALUE, MPFROMP(&ParamBlock.ulRings), MPFROM2SHORT(0, 0));
  575.          ParamBlock.fTitles=(USHORT)WinSendDlgItemMsg(hwnd, IDC_TITLES, BM_QUERYCHECK, NULL, NULL);
  576.          WinDismissDlg(hwnd, TRUE);
  577.  
  578.          WriteSettings2IniFile();
  579.          QueueData(IM_INICHANGED, NULL, 0l);
  580.          break;
  581.  
  582.       case DID_CANCEL:
  583.          WinDismissDlg(hwnd, FALSE);
  584.          break;
  585.       }
  586.       break;
  587.    }
  588.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  589. }
  590.  
  591.  
  592. static void  AddMtoCnr
  593. (
  594.    HWND hwndCnr,
  595.    PEAOP2 peaop2
  596. )
  597. {
  598.    CHAR szDescr[MAXDESCR];
  599.    PFILEFINDBUF3 pfb;
  600.    ULONG ulLen, ulTimelength;
  601.    PFEA2LIST pfea2list;
  602.    PFEA2 pfea2;
  603.    PMYCORE pmc;
  604.    RECORDINSERT ri;
  605.    PCHAR pszName;
  606.  
  607.    pfb=(PFILEFINDBUF3)(peaop2+1);
  608.    pfea2list=(PFEA2LIST)&pfb->cchName;
  609.    pszName=(PCHAR)pfea2list+pfea2list->cbList+1;
  610.    pfea2=pfea2list->list;
  611.  
  612.    if (pfea2->cbValue == 2*sizeof (USHORT) + sizeof (ULONG) && *(PUSHORT)(pfea2->szName+pfea2->cbName+1) == EAT_BINARY)
  613.       ulTimelength=*(PULONG)(pfea2->szName+pfea2->cbName+1+2*sizeof(USHORT));
  614.    else
  615.       ulTimelength=pfb->cbFile / 2000; // Estimate time based on size
  616.  
  617.    pfea2= (PFEA2)((PCHAR)pfea2+pfea2->oNextEntryOffset);
  618.  
  619.    *szDescr='\0';
  620.    if (pfea2->cbValue >= 2*sizeof (USHORT) && *(PUSHORT)(pfea2->szName+pfea2->cbName+1) == EAT_ASCII)
  621.    {
  622.       ulLen = *(PUSHORT)(pfea2->szName+pfea2->cbName+1+sizeof(USHORT));
  623.       if (ulLen > 0 && ulLen <= pfea2->cbValue - 2*sizeof (USHORT))
  624.       {
  625.          ulLen = min(ulLen, sizeof szDescr-1);
  626.          memcpy(szDescr, pfea2->szName+pfea2->cbName+1+2*sizeof(USHORT), ulLen);
  627.          szDescr[ulLen]='\0';
  628.       }
  629.    }
  630.  
  631.    pmc = WinSendMsg(hwndCnr, CM_ALLOCRECORD, MPFROMLONG(sizeof (MYCORE) - sizeof (MINIRECORDCORE)), MPFROMSHORT(1));
  632.    pmc->hptr=hptrMsg;
  633.    pmc->pszDescr=strdup(szDescr);
  634.    pmc->pszFile=strdup(pszName);
  635.    pmc->date.year=pfb->fdateLastWrite.year+1980;
  636.    pmc->date.month=pfb->fdateLastWrite.month;
  637.    pmc->date.day=pfb->fdateLastWrite.day;
  638.    pmc->time.hours=pfb->ftimeLastWrite.hours;
  639.    pmc->time.minutes=pfb->ftimeLastWrite.minutes;
  640.    pmc->time.seconds=0;
  641.    pmc->ulLen=ulTimelength;
  642.    ri.cb = sizeof ri;
  643.    ri.pRecordOrder = (PRECORDCORE)CMA_END;
  644.    ri.pRecordParent = NULL;
  645.    ri.zOrder = CMA_TOP;
  646.    ri.cRecordsInsert = 1;
  647.    ri.fInvalidateRecord = TRUE;
  648.  
  649.    WinSendMsg(hwndCnr, CM_INSERTRECORD, MPFROMP(pmc), MPFROMP(&ri));
  650. }
  651.  
  652.  
  653. static PGEA2LIST GetGEA2List
  654. (
  655.    void
  656. )
  657. {
  658.    PGEA2LIST pgea2list;
  659.    PGEA2 pgea2;
  660.  
  661.    pgea2list = malloc(2*(sizeof *pgea2list - 1 + 3) + sizeof szEALen + sizeof szEADescr); // Allocates a litle extra (I'm lazy)
  662.  
  663.  
  664.    pgea2 = pgea2list->list;
  665.  
  666.    pgea2->oNextEntryOffset = (sizeof *pgea2 - 1 + sizeof szEALen + 3) & ~3;
  667.    pgea2->cbName = sizeof szEALen-1;
  668.    memcpy(pgea2->szName, szEALen, sizeof szEALen);
  669.  
  670.    pgea2 = (PGEA2)((PCHAR)pgea2+pgea2->oNextEntryOffset);
  671.  
  672.    pgea2->oNextEntryOffset = 0;
  673.    pgea2->cbName = sizeof szEADescr-1;
  674.    memcpy(pgea2->szName, szEADescr, sizeof szEADescr);
  675.  
  676.    pgea2list->cbList = ((PCHAR)pgea2+sizeof *pgea2 - 1 + sizeof szEADescr) - (PCHAR)pgea2list->list;
  677.  
  678.    return pgea2list;
  679. }
  680.  
  681.  
  682. static void ScanDir4M
  683. (
  684.    HWND hwndCnr
  685. )
  686. {
  687.    HDIR hDir=HDIR_CREATE;
  688.    ULONG usFiles=1, usFound=0, res, ulBuffLen;
  689.    PEAOP2 peaop2;
  690.    PMYCORE pmc=NULL;
  691.    CHAR szFilePattern[80];
  692.  
  693.    WinEnableWindowUpdate(hwndCnr, FALSE);
  694.  
  695.    // Remove old contents
  696.    for (;;)
  697.    {
  698.       pmc = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pmc), MPFROM2SHORT(pmc ? CMA_NEXT : CMA_FIRST, CMA_ITEMORDER));
  699.       if (pmc == NULL || (ULONG)pmc == 0xffff)
  700.          break;
  701.  
  702.       if (pmc->pszDescr != NULL)
  703.          free(pmc->pszDescr);
  704.       free(pmc->pszFile);
  705.    }
  706.  
  707.    WinSendMsg(hwndCnr, CM_REMOVERECORD, 0, MPFROM2SHORT(0, CMA_FREE | CMA_INVALIDATE));
  708.  
  709.    ulBuffLen = sizeof *peaop2 + 2*sizeof(GEA2LIST) + sizeof(FILEFINDBUF3) + 6*sizeof (ULONG) + 100;
  710.    peaop2 = malloc(ulBuffLen);
  711.    peaop2->fpGEA2List = GetGEA2List();
  712.  
  713.    sprintf(szFilePattern, ParamBlock.szMessagePattern, "*");
  714.    res=DosFindFirst(szFilePattern, &hDir, FILE_NORMAL, peaop2, ulBuffLen, &usFiles, FIL_QUERYEASFROMLIST);
  715.    while (res==0)
  716.    {
  717.       usFound++;
  718.  
  719.       AddMtoCnr(hwndCnr, peaop2);
  720.  
  721.       res=DosFindNext(hDir, peaop2, ulBuffLen, &usFiles);
  722.    }
  723.  
  724.    ulRecMessages=usFound;
  725.    free(peaop2->fpGEA2List);
  726.    free(peaop2);
  727.  
  728.    WinShowWindow(hwndCnr, TRUE);
  729.  
  730.    if (usFound)
  731.       DosFindClose(hDir);
  732. }
  733.  
  734.  
  735. #if 0
  736. static void AddMFile
  737. (
  738.    HWND hwndLB,
  739.    PCHAR pszFile
  740. )
  741. {
  742.    HDIR hDir=HDIR_CREATE;
  743.    ULONG usFiles=1, res, ulBuffLen;
  744.    PEAOP2 peaop2;
  745.  
  746.    ulBuffLen = sizeof *peaop2 + 2*sizeof(GEA2LIST) + sizeof(FILEFINDBUF3) + 6*sizeof (ULONG) + 100;
  747.    peaop2 = malloc(ulBuffLen);
  748.    peaop2->fpGEA2List = GetGEA2List();
  749.  
  750.    res=DosFindFirst(pszFile, &hDir, FILE_NORMAL, peaop2, ulBuffLen, &usFiles, FIL_QUERYEASFROMLIST);
  751.    if (res==0)
  752.    {
  753.       AddMtoLB(hwndLB, peaop2);
  754.       DosFindClose(hDir);
  755.    }
  756.  
  757.    free(peaop2->fpGEA2List);
  758.    free(peaop2);
  759. }
  760. #endif
  761.  
  762. static void PlaySelected
  763. (
  764.    HWND hwndCnr
  765. )
  766. {
  767.    PMYCORE pmc=(PMYCORE)CMA_FIRST;
  768.  
  769.    for (;;)
  770.    {
  771.       pmc = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pmc), MPFROMSHORT(CRA_SELECTED));
  772.       if (pmc == NULL || (ULONG)pmc == 0xffff)
  773.          break;
  774.  
  775.       QueueData(IM_PLAY, pmc->pszFile, strlen(pmc->pszFile)+1);
  776.    }
  777. }
  778.  
  779.  
  780. static void DeleteSelected
  781. (
  782.    HWND hwndCnr
  783. )
  784. {
  785.    PMYCORE pmc;
  786.  
  787.    WinEnableWindowUpdate(hwndCnr, FALSE);
  788.    for (;;)
  789.    {
  790.       pmc=(PMYCORE)CMA_FIRST;
  791.  
  792.       pmc = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pmc), MPFROMSHORT(CRA_SELECTED));
  793.       if (pmc == NULL || (ULONG)pmc == 0xffff)
  794.          break;
  795.  
  796.       QueueData(IM_DELETE, pmc->pszFile, strlen(pmc->pszFile)+1);
  797.  
  798.       if (pmc->pszDescr != NULL)
  799.          free(pmc->pszDescr);
  800.  
  801.       WinSendMsg(hwndCnr, CM_REMOVERECORD, MPFROMP(&pmc), MPFROM2SHORT(1, CMA_FREE | CMA_INVALIDATE));
  802.    }
  803.    WinShowWindow(hwndCnr, TRUE);
  804. }
  805.  
  806.  
  807. static void InitCnr
  808. (
  809.    HWND hwndCnr
  810. )
  811. {
  812.    CNRINFO cnrInfo;
  813.    PFIELDINFO pfiStart, pfi;
  814.    FIELDINFOINSERT fii;
  815.    USHORT res;
  816.  
  817.    pfiStart = WinSendMsg(hwndCnr, CM_ALLOCDETAILFIELDINFO, MPFROMSHORT(CNRCOLS), 0l);
  818.    pfi = pfiStart;
  819.  
  820.    #if 0
  821.    pfi->flData = CFA_BITMAPORICON | CFA_VCENTER | CFA_CENTER | CFA_SEPARATOR | CFA_FIREADONLY;
  822.    pfi->flTitle = CFA_FITITLEREADONLY;
  823.    pfi->pTitleData = "";
  824.    pfi->offStruct = sizeof (MINIRECORDCORE);
  825.    pfi = pfi->pNextFieldInfo;
  826.    #endif
  827.  
  828.    pfi->flData = CFA_DATE | CFA_VCENTER | CFA_LEFT | CFA_HORZSEPARATOR | CFA_SEPARATOR | CFA_FIREADONLY;
  829.    pfi->flTitle = CFA_FITITLEREADONLY;
  830.    pfi->pTitleData = "Date";
  831.    pfi->offStruct = sizeof (MINIRECORDCORE) + sizeof (HPOINTER);
  832.  
  833.    pfi = pfi->pNextFieldInfo;
  834.    pfi->flData = CFA_TIME | CFA_VCENTER | CFA_LEFT | CFA_HORZSEPARATOR| CFA_SEPARATOR | CFA_FIREADONLY;
  835.    pfi->flTitle = CFA_FITITLEREADONLY;
  836.    pfi->pTitleData = "Time";
  837.    pfi->offStruct = sizeof (MINIRECORDCORE) + sizeof (HPOINTER) + sizeof (CDATE);
  838.  
  839.    pfi = pfi->pNextFieldInfo;
  840.    pfi->flData = CFA_ULONG | CFA_VCENTER | CFA_RIGHT | CFA_HORZSEPARATOR| CFA_SEPARATOR | CFA_FIREADONLY;
  841.    pfi->flTitle = CFA_FITITLEREADONLY;
  842.    pfi->pTitleData = "Length";
  843.    pfi->offStruct = sizeof (MINIRECORDCORE) + sizeof (HPOINTER) + sizeof (CDATE) + sizeof(CTIME);
  844.  
  845.    pfi = pfi->pNextFieldInfo;
  846.    pfi->flData = CFA_STRING | CFA_VCENTER | CFA_LEFT | CFA_HORZSEPARATOR| CFA_SEPARATOR | CFA_FIREADONLY;
  847.    pfi->flTitle = CFA_FITITLEREADONLY;
  848.    pfi->pTitleData = "Description";
  849.    pfi->offStruct = sizeof (MINIRECORDCORE) + sizeof (HPOINTER) + sizeof (CDATE) + sizeof(CTIME) + sizeof (ULONG);
  850.  
  851.    fii.cb = sizeof fii;
  852.    fii.pFieldInfoOrder = (PFIELDINFO)CMA_END;
  853.    fii.cFieldInfoInsert = CNRCOLS;
  854.    fii.fInvalidateFieldInfo = TRUE;
  855.  
  856.    res=(USHORT)WinSendMsg(hwndCnr, CM_INSERTDETAILFIELDINFO, MPFROMP(pfiStart), MPFROMP(&fii));
  857.    if (fDebug)
  858.       dprintf("%u fields added to container\n", res);
  859.  
  860.    cnrInfo.cb = sizeof cnrInfo;
  861.    cnrInfo.flWindowAttr = CV_DETAIL;
  862.    cnrInfo.slBitmapOrIcon.cx=WinQuerySysValue(HWND_DESKTOP, SV_CYMENU)*4/5;
  863.    cnrInfo.slBitmapOrIcon.cy=WinQuerySysValue(HWND_DESKTOP, SV_CYMENU)*4/5;
  864.  
  865.    if (ParamBlock.fTitles)
  866.       cnrInfo.flWindowAttr |= CA_DETAILSVIEWTITLES;
  867.  
  868. // cnrInfo.pFieldInfoObject = afi;
  869.  
  870.    WinSendMsg(hwndCnr, CM_SETCNRINFO, MPFROMP(&cnrInfo), MPFROMLONG(CMA_FLWINDOWATTR | CMA_SLBITMAPORICON));
  871. }
  872.  
  873.  
  874. static void UpdateViewSettings
  875. (
  876.    HWND hwndCnr
  877. )
  878. {
  879.    CNRINFO cnrInfo;
  880.  
  881.    WinSendMsg(hwndCnr, CM_QUERYCNRINFO, MPFROMP(&cnrInfo), MPFROMSHORT(sizeof cnrInfo));
  882.  
  883.    if (ParamBlock.fTitles)
  884.       cnrInfo.flWindowAttr |= CA_DETAILSVIEWTITLES;
  885.    else
  886.       cnrInfo.flWindowAttr &= ~CA_DETAILSVIEWTITLES;
  887.  
  888.    WinSendMsg(hwndCnr, CM_SETCNRINFO, MPFROMP(&cnrInfo), MPFROMLONG(CMA_FLWINDOWATTR));
  889. }
  890.  
  891.  
  892. static void DoARecording
  893. (
  894.    HWND hwnd
  895. )
  896. {
  897.    FILEDLG pfdFiledlg;
  898.     
  899.    static char pszTitle[] = "Record File";
  900.    char pszFullFile[CCHMAXPATH];
  901.    HWND hwndDlg;
  902.    static char * apszFilter[] = {szOurEAType, NULL};
  903.    strcpy(pszFullFile, "*.");
  904.    strcat(pszFullFile, ParamBlock.szFileExtension);
  905.  
  906.    memset(&pfdFiledlg, 0, sizeof(FILEDLG));
  907.  
  908.    pfdFiledlg.cbSize = sizeof(FILEDLG);
  909.    pfdFiledlg.fl = FDS_CENTER | FDS_SAVEAS_DIALOG | FDS_ENABLEFILELB;
  910.    pfdFiledlg.pszTitle = pszTitle;
  911.    strcpy(pfdFiledlg.szFullFile, pszFullFile);
  912.    pfdFiledlg.papszITypeList=(PAPSZ)apszFilter;
  913. // pfdFiledlg.pszIType=apszFilter[0];
  914.  
  915.    hwndDlg = WinFileDlg(HWND_DESKTOP, hwnd, &pfdFiledlg);
  916.  
  917.    if (hwndDlg && (pfdFiledlg.lReturn == DID_OK))
  918.    {
  919.       if (fDebug)
  920.          dprintf("File '%s' selected\n", pfdFiledlg.szFullFile);
  921.       QueueData(IM_RECORD, pfdFiledlg.szFullFile, strlen(pfdFiledlg.szFullFile)+1);
  922.    }
  923. }
  924.  
  925.  
  926. static void DoPlayFile
  927. (
  928.    HWND hwnd
  929. )
  930. {
  931.    FILEDLG pfdFiledlg;
  932.     
  933.    static char pszTitle[] = "Play File";
  934.    char pszFullFile[CCHMAXPATH];
  935.    HWND hwndDlg;
  936.    static char * apszFilter[] = {szOurEAType, NULL};
  937.  
  938.    strcpy(pszFullFile, "*.");
  939.    strcat(pszFullFile, ParamBlock.szFileExtension);
  940.  
  941.    memset(&pfdFiledlg, 0, sizeof(FILEDLG));
  942.  
  943.    pfdFiledlg.cbSize = sizeof(FILEDLG);
  944.    pfdFiledlg.fl = FDS_CENTER | FDS_OPEN_DIALOG;
  945.    pfdFiledlg.pszTitle = pszTitle;
  946.    strcpy(pfdFiledlg.szFullFile, pszFullFile);
  947.    pfdFiledlg.papszITypeList=(PAPSZ)apszFilter;
  948. // pfdFiledlg.pszIType=apszFilter[0];
  949.  
  950.    hwndDlg = WinFileDlg(HWND_DESKTOP, hwnd, &pfdFiledlg);
  951.  
  952.    if (hwndDlg && (pfdFiledlg.lReturn == DID_OK))
  953.    {
  954.       if (fDebug)
  955.          dprintf("File '%s' selected\n", pfdFiledlg.szFullFile);
  956.       QueueData(IM_PLAY, pfdFiledlg.szFullFile, strlen(pfdFiledlg.szFullFile)+1);
  957.    }
  958. }
  959.  
  960.  
  961. MRESULT EXPENTRY ClientWndProc
  962. (
  963.    HWND   hwnd,
  964.    USHORT msg,
  965.    MPARAM mp1,
  966.    MPARAM mp2
  967. )
  968. {
  969.    HWND hwndTmp;
  970.    SWP swp;
  971.    RECTL rectl, rectl2;
  972.    HPS hps;
  973.  
  974.    switch (msg)
  975.    {
  976.    case WM_INITDLG:
  977.       WinRestoreWindowPos(szAppName, szAppPosOrgKey, hwnd);
  978.       hwndTmp=WinWindowFromID(hwnd, IDC_CALLLIST);
  979.       InitCnr(hwndTmp);
  980.       ScanDir4M(hwndTmp);
  981.       return (MRESULT)TRUE;
  982.  
  983.    case WM_CLOSE:
  984.       if (fDebug)
  985.          dprintf("Close pressed\n");
  986.       QueueData(IM_DOWN, NULL, 0l);
  987.       WinStoreWindowPos(szAppName, szAppPosOrgKey, hwnd);
  988.       break;
  989.  
  990.    case WM_PAINT:
  991.       WinQueryWindowPos(hwnd, &swp);
  992.       if (swp.fl & SWP_MINIMIZE)
  993.       {
  994.          WinQueryWindowRect(hwnd, &rectl);
  995.          hps=WinBeginPaint(hwnd, NULLHANDLE, &rectl2);
  996.          WinFillRect(hps, &rectl2, ulRecMessages ? CLR_RED : CLR_GREEN);
  997.          WinEndPaint(hps);
  998.          return 0;
  999.       }
  1000.       break;
  1001.  
  1002.    case WM_COMMAND:
  1003.       switch (COMMANDMSG(&msg)->cmd)
  1004.       {
  1005.       case 1:  // Ok
  1006.       case DID_CANCEL:
  1007.          return 0;
  1008.  
  1009.       case IDM_ABOUT:
  1010.          WinDlgBox(HWND_DESKTOP, hwnd, (PFNWP)AboutDlgProc, 0l, IDD_ABOUT, 0l);
  1011.          return 0;
  1012.  
  1013.       case IDM_SETTINGS:
  1014.          if (WinDlgBox(HWND_DESKTOP, hwnd, (PFNWP)SettingsDlgProc, 0l, IDD_SETTINGS, 0l))
  1015.             UpdateViewSettings(WinWindowFromID(hwnd, IDC_CALLLIST));
  1016.          return 0;
  1017.  
  1018.       case IDC_ABORT:
  1019.          if (fDebug)
  1020.             dprintf("Abort pressed\n");
  1021.          fAbortCmd=TRUE;
  1022.          WinEnableWindow(WinWindowFromID(hwnd, IDC_ABORT), FALSE);
  1023.          QueueData(IM_ABORT, NULL, 0l);
  1024.          return 0;
  1025.  
  1026.       case IDC_RELEASE:
  1027.          QueueData(IM_RELEASE, NULL, 0l);
  1028.          return 0;
  1029.  
  1030.       case IDC_PLAY:
  1031.          PlaySelected(WinWindowFromID(hwnd, IDC_CALLLIST));
  1032.          return 0;
  1033.  
  1034.       case IDC_DELETE:
  1035.          DeleteSelected(WinWindowFromID(hwnd, IDC_CALLLIST));
  1036.          return 0;
  1037.  
  1038.       case IDM_RECORD:
  1039.          DoARecording(hwnd);
  1040.          return 0;
  1041.  
  1042.       case IDM_PLAYFILE:
  1043.          DoPlayFile(hwnd);
  1044.          return 0;
  1045.       }
  1046.       break;
  1047.  
  1048.    case WM_CONTROL:
  1049.       switch (SHORT1FROMMP(mp1))
  1050.       {
  1051.       case IDC_CALLLIST:
  1052.          if (SHORT2FROMMP(mp1)==CN_ENTER)
  1053.             PlaySelected(WinWindowFromID(hwnd, IDC_CALLLIST));
  1054.          break;
  1055.       }
  1056.       break;
  1057.  
  1058.    case WMU_THREADSUP:
  1059.       if (fDebug)
  1060.          dprintf("Got THREADSUP\n");
  1061.       return 0;
  1062.    case WMU_BUSYCMD:
  1063.       WinEnableWindow(WinWindowFromID(hwnd, IDC_ABORT), TRUE);
  1064.       WinEnableWindow(WinWindowFromID(hwnd, IDC_RELEASE), FALSE);
  1065.       return 0;
  1066.    case WMU_IDLECMD:
  1067.       WinEnableWindow(WinWindowFromID(hwnd, IDC_ABORT), FALSE);
  1068.       WinEnableWindow(WinWindowFromID(hwnd, IDC_RELEASE), TRUE);
  1069.       WinEnableWindow(WinWindowFromID(hwnd, IDC_PLAY), TRUE);
  1070.       WinEnableWindow(WinWindowFromID(hwnd, IDC_DELETE), TRUE);
  1071.       return 0;
  1072.    case WMU_NOCOM:
  1073.       WinEnableWindow(WinWindowFromID(hwnd, IDC_RELEASE), FALSE);
  1074.       WinEnableWindow(WinWindowFromID(hwnd, IDC_PLAY), FALSE);
  1075.       WinEnableWindow(WinWindowFromID(hwnd, IDC_DELETE), FALSE);
  1076.       return 0;
  1077.    case WMU_THREADSDOWN:
  1078.       if (fDebug)
  1079.          dprintf("Got THREADSDOWN\n");
  1080.       WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
  1081.       return 0;
  1082.    case WMU_STATE:
  1083.       WinSetDlgItemText(hwnd, IDC_STATE, PVOIDFROMMP(mp1));
  1084.       free(PVOIDFROMMP(mp1));
  1085.       return 0;
  1086.    case WMU_LASTDCE:
  1087.       WinSetDlgItemText(hwnd, IDC_DCERESPONSE, PVOIDFROMMP(mp1));
  1088.       free(PVOIDFROMMP(mp1));
  1089.       return 0;
  1090.    case WMU_UPDLIST:
  1091.       if (fDebug)
  1092.          dprintf("Got UPDLIST\n");
  1093.       ScanDir4M(WinWindowFromID(hwnd, IDC_CALLLIST));
  1094.       return 0;
  1095.    #if 0
  1096.    case WMU_ADDLIST:
  1097.       if (fDebug)
  1098.          dprintf("Got ADDLIST\n");
  1099.       AddMFile(WinWindowFromID(hwnd, IDC_CALLLIST), PVOIDFROMMP(mp1));
  1100.       free(PVOIDFROMMP(mp1));
  1101.       return 0;
  1102.    #endif
  1103.    }
  1104.    return WinDefDlgProc (hwnd, msg, mp1, mp2);
  1105. }
  1106.  
  1107.  
  1108. MRESULT EXPENTRY Am4PmWndProc
  1109. (
  1110.    HWND   hwnd,
  1111.    ULONG  msg,
  1112.    MPARAM mp1,
  1113.    MPARAM mp2
  1114. )
  1115. {
  1116.    PSWP pswp;
  1117.    POINTL ptl;
  1118.    MRESULT mr;
  1119.    static LONG lCyMenu;
  1120.  
  1121.  
  1122.    switch (msg)
  1123.    {
  1124.    case WM_CREATED:
  1125.       lCyMenu=WinQuerySysValue(HWND_DESKTOP, SV_CYMENU);
  1126.       WinCreateWindow(hwnd, WC_STATIC, "", WS_VISIBLE | SS_TEXT | DT_CENTER, 0, 0, 0, 0, hwnd, HWND_TOP, IDC_DCERESPONSE, NULL, NULL);
  1127.       WinCreateWindow(hwnd, WC_STATIC, "Started", WS_VISIBLE | SS_TEXT, 0, 0, 0, 0, hwnd, HWND_TOP, IDC_STATE, NULL, NULL);
  1128.  
  1129.       if (fDebug)
  1130.          dprintf("Got CREATED\n");
  1131.       InitCnr(hwndClient);
  1132.       ScanDir4M(hwndClient);
  1133.       return 0;
  1134.  
  1135.    case WM_CLOSE:
  1136.       if (fDebug)
  1137.          dprintf("Close pressed\n");
  1138.       QueueData(IM_DOWN, NULL, 0l);
  1139.       return 0;
  1140.  
  1141.    #if 0
  1142.    case WM_PAINT:
  1143.       WinQueryWindowPos(hwnd, &swp);
  1144.       if (swp.fl & SWP_MINIMIZE)
  1145.       {
  1146.          WinQueryWindowRect(hwnd, &rectl);
  1147.          hps=WinBeginPaint(hwnd, NULLHANDLE, &rectl2);
  1148.          WinFillRect(hps, &rectl2, ulRecMessages ? CLR_RED : CLR_GREEN);
  1149.          WinEndPaint(hps);
  1150.          return 0;
  1151.       }
  1152.       break;
  1153.    #endif
  1154.  
  1155.    case WM_SYSCOMMAND:
  1156.       if (SHORT1FROMMP(mp1) == SC_CLOSE)
  1157.       {
  1158.          if (fDebug)
  1159.             dprintf("Close pressed\n");
  1160.          QueueData(IM_DOWN, NULL, 0l);
  1161.          return 0;
  1162.       }
  1163.       break;
  1164.  
  1165.    case WM_COMMAND:
  1166.       switch (COMMANDMSG(&msg)->cmd)
  1167.       {
  1168.       case 1:  // Ok
  1169.       case DID_CANCEL:
  1170.          return 0;
  1171.  
  1172.       case IDM_ABOUT:
  1173.          WinDlgBox(HWND_DESKTOP, hwnd, (PFNWP)AboutDlgProc, 0l, IDD_ABOUT, 0l);
  1174.          return 0;
  1175.  
  1176.       case IDM_SETTINGS:
  1177.          if (WinDlgBox(HWND_DESKTOP, hwnd, (PFNWP)SettingsDlgProc, 0l, IDD_SETTINGS, 0l))
  1178.             UpdateViewSettings(hwndClient);
  1179.          return 0;
  1180.  
  1181.       case IDM_ABORT:
  1182.          if (fDebug)
  1183.             dprintf("Abort pressed\n");
  1184.          fAbortCmd=TRUE;
  1185.          WinEnableMenuItem(hwndMenu, IDM_ABORT, FALSE);
  1186.          WinEnableMenuItem(hwndMenu, IDM_STOP, FALSE);
  1187.          QueueData(IM_ABORT, NULL, 0l);
  1188.          return 0;
  1189.  
  1190.       case IDM_RELEASE:
  1191.          QueueData(IM_RELEASE, NULL, 0l);
  1192.          return 0;
  1193.  
  1194.       case IDM_STOP:
  1195.          QueueData(IM_STOP, NULL, 0l);
  1196.          return 0;
  1197.  
  1198.       case IDM_PLAY:
  1199.          PlaySelected(hwndClient);
  1200.          return 0;
  1201.  
  1202.       case IDM_DELETE:
  1203.          DeleteSelected(hwndClient);
  1204.          return 0;
  1205.  
  1206.       case IDM_RECORD:
  1207.          DoARecording(hwndClient);
  1208.          return 0;
  1209.  
  1210.       case IDM_PLAYFILE:
  1211.          DoPlayFile(hwndClient);
  1212.          return 0;
  1213.       }
  1214.       break;
  1215.  
  1216.    case WM_CONTROL:
  1217.       if (SHORT1FROMMP(mp1) == FID_CLIENT)
  1218.       {
  1219.          switch(SHORT2FROMMP(mp1))
  1220.          {
  1221.          case CN_ENTER:
  1222.             PlaySelected(hwndClient);
  1223.             return 0;
  1224.  
  1225.          case CN_CONTEXTMENU:
  1226.             if (fDebug)
  1227.                dprintf("WM_CONTEXTMENU\n");
  1228.             WinQueryMsgPos(hab, &ptl);
  1229.             WinPopupMenu(HWND_DESKTOP, hwnd, hwndMenu, ptl.x, ptl.y, IDM_PLAY, PU_POSITIONONITEM | PU_HCONSTRAIN | PU_VCONSTRAIN | PU_KEYBOARD | PU_MOUSEBUTTON1);
  1230.             return 0;
  1231.          }
  1232.          break;
  1233.       }
  1234.       break;
  1235.  
  1236.    case WM_OPEN:
  1237.       if (fDebug)
  1238.          dprintf("WM_OPEN\n");
  1239.       break;
  1240.  
  1241.    case WMU_THREADSUP:
  1242.       if (fDebug)
  1243.          dprintf("Got THREADSUP\n");
  1244.       return 0;
  1245.  
  1246.    case WMU_BUSYCMD:
  1247.       WinEnableMenuItem(hwndMenu, IDM_STOP, TRUE);
  1248.       WinEnableMenuItem(hwndMenu, IDM_ABORT, TRUE);
  1249.       WinEnableMenuItem(hwndMenu, IDM_RELEASE, FALSE);
  1250.       return 0;
  1251.  
  1252.    case WMU_IDLECMD:
  1253.       WinEnableMenuItem(hwndMenu, IDM_STOP, FALSE);
  1254.       WinEnableMenuItem(hwndMenu, IDM_ABORT, FALSE);
  1255.       WinEnableMenuItem(hwndMenu, IDM_RELEASE, TRUE);
  1256.       WinEnableMenuItem(hwndMenu, IDM_PLAY, TRUE);
  1257.       WinEnableMenuItem(hwndMenu, IDM_DELETE, TRUE);
  1258.       return 0;
  1259.  
  1260.    case WMU_NOCOM:
  1261.       WinEnableMenuItem(hwndMenu, IDM_RELEASE, FALSE);
  1262.       WinEnableMenuItem(hwndMenu, IDM_PLAY, FALSE);
  1263.       WinEnableMenuItem(hwndMenu, IDM_DELETE, FALSE);
  1264.       return 0;
  1265.  
  1266.    case WMU_THREADSDOWN:
  1267.       if (fDebug)
  1268.          dprintf("Got THREADSDOWN\n");
  1269.       WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
  1270.       return 0;
  1271.    case WMU_STATE:
  1272.       WinSetDlgItemText(hwnd, IDC_STATE, PVOIDFROMMP(mp1));
  1273.       free(PVOIDFROMMP(mp1));
  1274.       return 0;
  1275.    case WMU_LASTDCE:
  1276.       WinSetDlgItemText(hwnd, IDC_DCERESPONSE, PVOIDFROMMP(mp1));
  1277.       free(PVOIDFROMMP(mp1));
  1278.       return 0;
  1279.    case WMU_UPDLIST:
  1280.       if (fDebug)
  1281.          dprintf("Got UPDLIST\n");
  1282.       ScanDir4M(hwndClient);
  1283.       return 0;
  1284.  
  1285.    case WM_CALCFRAMERECT:
  1286.       if (!mp2)
  1287.          ((PRECTL)(mp1))->yBottom -= lCyMenu;
  1288.       mr = pfnwpFrame(hwnd, msg, mp1, mp2);
  1289.       if (mr && mp2)
  1290.          ((PRECTL)(mp1))->yBottom += lCyMenu;
  1291.       return mr;
  1292.  
  1293.    case WM_FORMATFRAME:
  1294.       mr = pfnwpFrame(hwnd, msg, mp1, mp2);
  1295.       pswp = ((PSWP)mp1) + (SHORT)mr - 1; // Point to client window
  1296.  
  1297. //    pswp[1] = pswp[0];
  1298.  
  1299.       pswp[2].cy = lCyMenu;
  1300.       pswp[2].cx = pswp[0].cx/2;
  1301.       pswp[2].y  = pswp[0].y;
  1302.       pswp[2].x  = pswp[0].x;
  1303.       pswp[2].fl = pswp[0].fl;
  1304.       pswp[2].hwnd = WinWindowFromID(hwnd, IDC_STATE);
  1305.       pswp[2].hwndInsertBehind = WinWindowFromID(hwnd, IDC_DCERESPONSE);
  1306.  
  1307.       pswp[1].cy = lCyMenu;
  1308.       pswp[1].cx = pswp[0].cx - pswp[2].cx;
  1309.       pswp[1].y  = pswp[0].y;
  1310.       pswp[1].x  = pswp[0].x + pswp[0].cx/2;
  1311.       pswp[1].fl = pswp[0].fl;
  1312.       pswp[1].hwnd = WinWindowFromID(hwnd, IDC_DCERESPONSE);
  1313.       pswp[1].hwndInsertBehind = pswp[0].hwndInsertBehind;
  1314.  
  1315.       pswp[0].y += lCyMenu;
  1316.       pswp[0].cy -= lCyMenu;
  1317.  
  1318.  
  1319.       return MRFROMSHORT(((SHORT)mr)+2);
  1320.  
  1321.    case WM_QUERYFRAMECTLCOUNT:
  1322.       mr = pfnwpFrame(hwnd, msg, mp1, mp2);
  1323.       return MRFROMSHORT(((SHORT)mr)+2);
  1324.  
  1325.    #if 0
  1326.    case WMU_ADDLIST:
  1327.       if (fDebug)
  1328.          dprintf("Got ADDLIST\n");
  1329.       AddMFile(hwndClient, PVOIDFROMMP(mp1));
  1330.       free(PVOIDFROMMP(mp1));
  1331.       return 0;
  1332.    #endif
  1333.    }
  1334.  
  1335.    return pfnwpFrame(hwnd, msg, mp1, mp2);
  1336. }
  1337.